package com.tf_cut.backend.payment.controller;

import com.bill99.asap.exception.CryptoException;
import com.bill99.asap.service.ICryptoService;
import com.bill99.asap.service.impl.CryptoServiceFactory;
import com.bill99.schema.asap.commons.Mpf;
import com.bill99.schema.asap.data.SealedData;
import com.bill99.schema.asap.data.UnsealedData;
import com.tf_cut.backend.agent.service.AgentCashOrderService;
import com.tf_cut.backend.payment.paydto.NotifyRequest;
import com.tf_cut.backend.payment.paydto.NotifyResponse;
import com.tf_cut.backend.payment.paydto.Pay2bankNotify;
import com.tf_cut.backend.payment.service.PaymentService;
import com.tf_cut.backend.util.CCSUtil;
import com.tf_cut.backend.util.CCSUtil_Query;
import com.tf_cut.backend.util.ConfigSettingUtil;
import com.tf_cut.backend.util.PKIUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

@RestController
@RequestMapping("/backend/paymentNotify")
@Slf4j
public class PaymentNotifyController {
    @Resource
    private ConfigSettingUtil configUtil;

    @Autowired
    private PaymentService paymentService;

    @Autowired
    private AgentCashOrderService agentCashOrderService;

    private Logger logger = LogManager.getLogger(PaymentNotifyController.class);

    @RequestMapping("notify")
    public void paymentResultNotify(HttpServletRequest httpRequest, HttpServletResponse httpResponse)  throws Exception {
        //获取客户端请求报文
        String requestXml = genRequestXml(httpRequest);

        logger.info("接收到第三方支付通知报文：" + requestXml);

        String membercode = configUtil.getConfigValue("payment","merchant_id"); //商户号
        String fetureCode = configUtil.getConfigValue("payment","feture_code"); //策略编码


        NotifyRequest request = CCSUtil.converyToJavaBean(requestXml, NotifyRequest.class);
        //解密请求报文
        SealedData sealedData = new SealedData();
        sealedData.setOriginalData(request.getNotifyRequestBody().getSealDataType().getOriginalData()==null?null: PKIUtil.utf8String2ByteWithBase64(request.getNotifyRequestBody().getSealDataType().getOriginalData()));
        sealedData.setSignedData(request.getNotifyRequestBody().getSealDataType().getSignedData()==null?null:PKIUtil.utf8String2ByteWithBase64(request.getNotifyRequestBody().getSealDataType().getSignedData()));
        sealedData.setEncryptedData(request.getNotifyRequestBody().getSealDataType().getEncryptedData()==null?null:PKIUtil.utf8String2ByteWithBase64(request.getNotifyRequestBody().getSealDataType().getEncryptedData()));
        sealedData.setDigitalEnvelope(request.getNotifyRequestBody().getSealDataType().getDigitalEnvelope()==null?null:PKIUtil.utf8String2ByteWithBase64(request.getNotifyRequestBody().getSealDataType().getDigitalEnvelope()));
        Mpf mpf = genMpf(fetureCode , membercode);
        UnsealedData unsealedData = null;
        try {
            ICryptoService service = CryptoServiceFactory.createCryptoService();
            unsealedData = service.unseal(mpf, sealedData);
        } catch (CryptoException e) {
            System.out.println(e);
        }
        byte[] decryptedData = unsealedData.getDecryptedData();
        String rtnString = "";
        if (null != decryptedData) {
            rtnString = PKIUtil.byte2UTF8String(decryptedData);
        } else {
            rtnString = PKIUtil.byte2UTF8String(sealedData.getOriginalData());
        }

        logger.info("解密后报文: " + rtnString);


        Pay2bankNotify respObj = CCSUtil_Query.converyToJavaBean(rtnString, Pay2bankNotify.class);



        //返回响应，表示已经正常接收通知
        sealxml(request, httpResponse, fetureCode, membercode);
    }

    private void sealxml(NotifyRequest request,HttpServletResponse httpResponse,String fetureCode,String membercode) throws IOException {
        String version = configUtil.getConfigValue("payment","version");        //接口版本
        String encoding = configUtil.getConfigValue("payment","encoding");      //字符编码
        Mpf mpf = genMpf(fetureCode , membercode);
        SealedData sealedData = null;
        try {
            ICryptoService service = CryptoServiceFactory.createCryptoService();
            sealedData = service.seal(mpf, request.getNotifyRequestBody().getSealDataType().getOriginalData().getBytes());
        } catch (CryptoException e) {
            System.out.println(e);
        }
        NotifyResponse response = CCSUtil.genResponse(membercode , version);
        byte[] nullbyte = {};
        byte[] byteOri = sealedData.getOriginalData() == null ? nullbyte : sealedData.getOriginalData();
        byte[] byteEnc = sealedData.getEncryptedData() == null ? nullbyte : sealedData.getEncryptedData();
        byte[] byteEnv = sealedData.getDigitalEnvelope() == null ? nullbyte : sealedData.getDigitalEnvelope();
        byte[] byteSig = sealedData.getSignedData() == null ? nullbyte : sealedData.getSignedData();
        response.getNotifyResponseBody().getSealDataType().setOriginalData(PKIUtil.byte2UTF8StringWithBase64(byteOri));
        //获取加签报文
        response.getNotifyResponseBody().getSealDataType().setSignedData(PKIUtil.byte2UTF8StringWithBase64(byteSig));
//		//获取加密报文
        response.getNotifyResponseBody().getSealDataType().setEncryptedData(PKIUtil.byte2UTF8StringWithBase64(byteEnc));
//		//数字信封
        response.getNotifyResponseBody().getSealDataType().setDigitalEnvelope(PKIUtil.byte2UTF8StringWithBase64(byteEnv));

        //请求报文
        String requestXml = CCSUtil.convertToXml(response, encoding);
        logger.info("组装响应密文: " + requestXml);

        //返回响应报文
        httpResponse.setCharacterEncoding(encoding);
        httpResponse.setContentType(encoding);
        httpResponse.getWriter().write(requestXml);
        httpResponse.getWriter().flush();
    }


    private String genRequestXml(HttpServletRequest httpRequest) throws IOException {
        String line = null;
        ServletInputStream is = null;
        InputStreamReader isr = null;
        BufferedReader br = null;
        StringBuffer sb = new StringBuffer();
        try {
            is = httpRequest.getInputStream();
            isr = new InputStreamReader(is, "utf-8");
            br = new BufferedReader(isr);
            while ((line = br.readLine()) != null) {
                sb.append(line);
                sb.append("\n");
            }
        } catch (IOException e) {
            logger.error("genRequestXml exception", e);
        } finally{
            try {
                if (null != is)is.close();
                if (null != isr)isr.close();
                if (null != br)br.close();
            } catch (Exception e) {
                logger.error("io close exception", e);
            }
        }

        return sb.toString();
    }

    public static Mpf genMpf(String fetureCode, String membercode) {
        Mpf mpf = new Mpf();
        mpf.setFeatureCode(fetureCode);
        mpf.setMemberCode(membercode);
        return mpf;
    }

    /*
       更换其他支付公司
     */
    /**
     * 费用发放 通知接口
     *
     * 请求数据示例：
     * http://www.xxx.com/xxx.aspx?ret_code=0000&ret_msg=查询成功&agent_id=1664502&hy_bill_no=
     * 5540780&status=1&batch_no=2017071819424142224&batch_amt=0.01&batch_num=1
     * &detail_data=20170713213543213514^6230521000000000005171^张三^0.01^S^
     * &ext_param1=测试&sign=b1cd61750ca1f16db54c861400616c7d
     *
     * ret_code 返回码值0000 表示查询成功
     * ret_msg  返回码信息提示
     * agent_id 商户编号，（汇付宝商户内码：七位整数数字）
     * hy_bill_no 汇付宝交易号(订单号)
     * status  -1=无效，0=未处理，1=成功
     * batch_no   商户系统内部的订单号
     * batch_amt   成功付款金额
     * batch_num   成功付款数量
     * detail_data  付款明细
     * 单笔数据集里面按照“商户流水号^收款人帐号^收款人姓名^付款金额^付款状态”来组织数据，
     * 每条整数据间用“|”符号分隔，付款状态S表示付款成功，状态F代表失败
     * ext_param1 商家数据包，原样返回
     * sign   	MD5\RSA\RSA2签名结果
     */
//    @RequestMapping("sellerNotify")
//    public String sellerNotify(String ret_code,String ret_msg,String agent_id,
//                               String hy_bill_no,String status,String batch_no,
//                               String batch_amt,String batch_num,String detail_data,
//                               String ext_param1,String sign) {
//
//        String key = configUtil.getConfigValue("payment","DesKey");                 //签名密钥
//
//        /*
//        签名规则：
//        sign=MD5(ret_code=0000&ret_msg=查询成功&agent_id=1664502
//        &hy_bill_no=5540780&status=1&batch_no=2017071819424142224
//        &batch_amt=0.01&batch_num=1
//        &detail_data=20170713213543213514^6230521000000000005171^张三^0.01^S^
//        &ext_param1=测试&key=d77686b728a6470e9e4e3f9a)
//        */
//        StringBuilder sign_sb = new StringBuilder("");
//
//        sign_sb.append("ret_code=").append(ret_code)
//        .append("&").append("ret_msg=").append(ret_msg)
//        .append("&").append("agent_id=").append(agent_id)
//        .append("&").append("hy_bill_no=").append(hy_bill_no)
//        .append("&").append("status=").append(status)
//        .append("&").append("batch_no=").append(batch_no)
//        .append("&").append("batch_amt=").append(batch_amt)
//        .append("&").append("batch_num=").append(batch_num)
//        .append("&").append("detail_data=").append(detail_data)
//        .append("&").append("ext_param1=").append(ext_param1)
//        .append("&").append("key=").append(key);
//
//        String sign_ = SmallTools.MD5en(sign_sb.toString().toLowerCase());
//
//        logger.info("第三方通知签名：" + sign);
//        logger.info("我方签名：" + sign_);
//
//        if(!sign_.equals(sign)){
//            logger.error("签名验证失败:");
//            return "error";
//        }
//
//        paymentService.updateDetail(detail_data);
//
//        return "succ";
//    }
//
//    @RequestMapping("agentNotify")
//    public String agentNotify(String ret_code,String ret_msg,String agent_id,
//                               String hy_bill_no,String status,String batch_no,
//                               String batch_amt,String batch_num,String detail_data,
//                               String ext_param1,String sign) {
//
//        String key = configUtil.getConfigValue("payment","key");                 //签名密钥
//        /*
//        签名规则：
//        sign=MD5(ret_code=0000&ret_msg=查询成功&agent_id=1664502
//        &hy_bill_no=5540780&status=1&batch_no=2017071819424142224
//        &batch_amt=0.01&batch_num=1
//        &detail_data=20170713213543213514^6230521000000000005171^张三^0.01^S^
//        &ext_param1=测试&key=d77686b728a6470e9e4e3f9a)
//        */
//        StringBuilder sign_sb = new StringBuilder("");
//
//        sign_sb.append("ret_code=").append(ret_code)
//                .append("&").append("ret_msg=").append(ret_msg)
//                .append("&").append("agent_id=").append(agent_id)
//                .append("&").append("hy_bill_no=").append(hy_bill_no)
//                .append("&").append("status=").append(status)
//                .append("&").append("batch_no=").append(batch_no)
//                .append("&").append("batch_amt=").append(batch_amt)
//                .append("&").append("batch_num=").append(batch_num)
//                .append("&").append("detail_data=").append(detail_data)
//                .append("&").append("ext_param1=").append(ext_param1)
//                .append("&").append("key=").append(key);
//
//        String sign_ = SmallTools.MD5en(sign_sb.toString().toLowerCase());
//
//        logger.info("第三方通知签名：" + sign);
//        logger.info("我方签名：" + sign_);
//
//        if(!sign_.equals(sign)){
//            logger.error("签名验证失败:");
//            return "error";
//        }
//
//
//
//        paymentService.updateAgentCash(batch_no,status);
//
//        return "succ";
//    }
}
